<html>
<head>
    <title>ThreeJs Webgl Performance</title>
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <style>
        body {
            font-family: Monospace;
            background-color: #000;
            color: #fff;
            margin: 0px;
            overflow: hidden;
        }

    </style>
</head>
<body>
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/libs/stats.min.js"></script>
<script src="https://threejs.org/examples/js/libs/dat.gui.min.js"></script>

<script>

    var camera, scene, renderer, stats, gui;
    var geometry, mesh;
    var amount = parseInt(window.location.search.substr(1)) || 4;
    var count = Math.pow(amount, 3);
    var dummy = new THREE.Object3D();
    init();
    animate();

    function init() {
        camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
        // camera.position.set(amount * 0.9, amount * 0.9, amount * 0.9);
        camera.position.set(0, 0, amount * 2);
        camera.lookAt(0, 0, 0);
        scene = new THREE.Scene();

        var axesHelper = new THREE.AxesHelper( 50 );
        scene.add( axesHelper );

        var light1 = new THREE.DirectionalLight(0xFFFFFF, 0.8);
        light1.position.set(1, 2, 3);
        scene.add(light1);

        var light2 = new THREE.HemisphereLight(0xffffbb, 0x080820, 0.8);
        scene.add(light2);

        var segments = 256;

        geometry = new THREE.SphereBufferGeometry(0.4, segments, segments);

        // check overdraw
        var material = new THREE.MeshPhongMaterial({color: 0xff0000});
        mesh = new THREE.InstancedMesh(geometry, material, count);

        mesh.triangles = geometry.index.count * mesh.count;
        mesh.vertices = geometry.attributes.position.count * mesh.count;
        mesh.targetFPS = 45;

        scene.add(mesh);
        //
        gui = new dat.GUI();
        gui.add(mesh, 'count', 1, count);
        gui.add(mesh, 'triangles');
        gui.add(mesh, 'vertices');
        gui.add(mesh, 'targetFPS', 15, 60);
        //init
        mesh.count = 64;


        //init matrix
        if (mesh) {
            var i = 0;
            var offset = -(amount-1) / 2;
            for (var x = 0; x < amount; x++) {
                for (var y = 0; y < amount; y++) {
                    for (var z = 0; z < amount; z++) {
                        dummy.position.set(offset + x, offset + y, offset + z);
                        // dummy.rotation.y = (Math.sin(x / 4 + time) + Math.sin(y / 4 + time) + Math.sin(z / 4 + time));
                        // dummy.rotation.z = dummy.rotation.y * 2;
                        dummy.updateMatrix();
                        mesh.setMatrixAt(i++, dummy.matrix);
                    }
                }
            }
            mesh.instanceMatrix.needsUpdate = true;
        }


        //
        renderer = new THREE.WebGLRenderer({antialias: true});
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);
        //
        stats = new Stats();
        document.body.appendChild(stats.dom);
        //
        window.addEventListener('resize', onWindowResize, false);
    }

    function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
    }

    //
    var t1 = 0;

    function animate() {
        requestAnimationFrame(animate);
        render();
        stats.update();

        // if (renderer.info.render.frame > 100) {
        //     if (renderer.info.render.frame % 10 === 0) {
        //         var time = performance.now() - t1;
        //         t1 = performance.now();
        //         // console.log(time);
        //         if (time <= 10 * 1000/mesh.targetFPS){
        //             mesh.count += 2;
        //         }else {
        //             mesh.count --;
        //         }
        //     }
        // }

    }

    function render() {
        var time = Date.now() * 0.001;
        mesh.rotation.x = Math.sin(time / 4);
        mesh.rotation.y = Math.sin(time / 2);

        mesh.count = mesh.count|0;
        mesh.triangles = geometry.index.count / 3 * mesh.count;
        mesh.vertices = geometry.attributes.position.count * mesh.count;
        gui.updateDisplay();

        renderer.render(scene, camera);
    }
</script>
</body>
</html>
